
import pylab as p
import math

from bpsk_modular_bits import modular_bits_en_bpsk
from funciones import generar_bits, sumar_ruido_gaussiano_blanco, detectar_bayesianamente
from funciones import calcular_estado_markov

N = 1000
alpha_0 = 0
alpha_1 = math.pi
A = 1
L = 8 
sigma2_W = 1
C_W = sigma2_W * p.identity(L)


def generar_y_detectar_recalculando_p01(generado, modulado_mas_ruido, lambda_01, lambda_11, P0_inicial, P1_inicial):
    
    #arranco en 1 para evitar la division por 0
    N_01 = [float(1), float(1)]
    P0 = P0_inicial
    P1 = P1_inicial
            
    detectado = []
    error = []
    for i in range(N):
        
        detectado_i = detectar_bayesianamente(modulado_mas_ruido[i * L:(i + 1) * L], A, alpha_0, alpha_1, C_W, P0, P1)
        detectado.append(detectado_i[0])
        error.append(detectado_i[1])

        #recalculo P0 y P1 con el promedio en cada paso
        N_01[0] = N_01[0] + (1 if detectado_i[0] == 0 else 0)
        N_01[1] = N_01[1] + (1 if detectado_i[0] == 1 else 0)
        P0 = N_01[0]/(N_01[0]+N_01[1])
        P1 = N_01[1]/(N_01[0]+N_01[1])

    contador = 0
    for i in range(N):
        if (generado[i] != detectado[i]):
            contador += 1       

    errores = contador / float(N)
    return (errores, P0, P1)

def generar_y_detectar(generado, modulado_mas_ruido, lambda_01, lambda_11, calcular_P01, P_01=None):
    assert((calcular_P01 != None) or (P_01 != None))
        
    detectado = []
    error = []
    for i in range(N):
        
        if calcular_P01:
            P_01 = calcular_P01(lambda_01, lambda_11, p.array([1-lambda_01, lambda_01]), i)
            
        detectado_i = detectar_bayesianamente(modulado_mas_ruido[i * L:(i + 1) * L], A, alpha_0, alpha_1, C_W, P_01[0], P_01[1])
        detectado.append(detectado_i[0])
        error.append(detectado_i[1])

    contador = 0
    for i in range(N):
        if (generado[i] != detectado[i]):
            contador += 1       

    errores = contador / float(N)
    return errores

if __name__ == '__main__':
    lambda_01 = 0.2
    lambda_11 = 0.4
    
    generado = generar_bits(lambda_01, lambda_11, N)
    modulado = modular_bits_en_bpsk(generado, alpha_0, alpha_1, A, L)
    modulado_mas_ruido = sumar_ruido_gaussiano_blanco(modulado, sigma2_W)
    
    (error, p0, p1) = generar_y_detectar_recalculando_p01(generado, modulado_mas_ruido, lambda_01, lambda_11, 0.5, 0.5)
    
    print "Deteccion bayesiaan calculando P0 y P1 en forma adaptativa"
    print "\t error: {}".format(error)
    print "\t P0={} P1={}".format(p0, p1)

    err_calculo = generar_y_detectar(generado, modulado_mas_ruido, lambda_01, lambda_11, calcular_estado_markov)
    [p0, p1] = calcular_estado_markov(lambda_01, lambda_11, [0.5,0.5], N)
    
    print "Deteccion bayesiaan calculando P0 y P1 con la matriz de markov"
    print "\t error: {}".format(err_calculo)
    print "\t P0={} P1={}".format(p0, p1)

